/**
 * Alipay.com Inc.
 * Copyright (c) 2004-2024 All Rights Reserved.
 */
package com.alipay.demo.spi;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.demo.util.AlipaySdkUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.Random;

/**
 * 凭证相关的spi接口
 * http(s)://{domain}/spi/certificate/xxx，其中 domain 需要为公网域名。
 *
 * @author jishupei.jsp
 * @version : MarketingCertificateSpiController, v0.1 2024年03月14日 5:18 下午 jishupei.jsp Exp $
 */
@RestController
@RequestMapping(value = "/spi/certificate")
public class MarketingCertificateSpiController {
    private static final Logger logger = LogManager.getLogger(MarketingCertificateSpiController.class);

    @Value("${alipay.appid}")
    private String appId;

    @Value("${alipay.privatekey}")
    private String privateKey;

    @Value("${alipay.alipaypublickey}")
    private String alipayPublicKey;

    @Autowired
    private AlipaySdkUtil alipaySdkUtil;

    /**
     * 三方凭证发放
     */
    @ResponseBody
    @PostMapping(value = "/send")
    public String send(@RequestParam Map<String, String> params) throws AlipayApiException {
        logger.info("收到支付宝 spi 接口调用, spi 接口: " + params.get("method") + ", 参数:" + JSON.toJSONString(params));

        JSONObject response = new JSONObject();
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8", "RSA2");
        // 获取待发放的商品信息
        JSONArray sendItemInfoList = JSONArray.parseArray(params.get("send_item_info_list"));

        if (CollectionUtils.isEmpty(sendItemInfoList)) {
            response.put("code", 40004);
            response.put("msg", "Business Failed");
            response.put("sub_code", "INVALID_PARAMETER");
            response.put("sub_msg", "参数有误,请检查参数");
            logger.error("执行失败，待发放的商品信息为空");
        } else if (!signVerified) {
            // 验签失败：构造错误码
            response.put("code", 40004);
            response.put("msg", "Business Failed");
            response.put("sub_code", "ISV-VERIFICATION-FAILED");
            response.put("sub_msg", "验签失败");
            logger.error("验签失败");
        } else {
            // 验签成功
            logger.info("order_id：" + params.get("order_id"));

            // 业务参数
            if (alipaySdkUtil.isUseOpenId()) {
                response.put("open_id", alipaySdkUtil.getOpenId());
            } else {
                response.put("user_id", alipaySdkUtil.getPid());
            }
            response.put("result_code", "SUCCESS");

            // 商家发放券码结果列表，需要和要求发码数量的结果保持一致，否则会认为发码失败
            JSONArray jsonArray = new JSONArray();
            for (int i = 0; i < sendItemInfoList.size(); i++) {
                JSONObject itemInfo = sendItemInfoList.getJSONObject(i);
                JSONObject sendCodeResult = new JSONObject();
                sendCodeResult.put("code", codeGenerator());
                sendCodeResult.put("out_item_id", itemInfo.getString("out_item_id"));
                sendCodeResult.put("item_id", itemInfo.getString("item_id"));
                sendCodeResult.put("out_sku_id", itemInfo.getString("out_sku_id"));
                sendCodeResult.put("sku_id", itemInfo.getString("sku_id"));
                jsonArray.add(sendCodeResult);
            }

            response.put("send_code_result_list", jsonArray);

            //spi 固定响应参数
            response.put("code", 10000);
            response.put("msg", "Success");
            logger.info("spi response：" + JSON.toJSONString(response));
        }
        String contentToSign = response.toJSONString();
        JSONObject spiResult = new JSONObject();
        String sign = AlipaySignature.rsaSign(contentToSign, privateKey, "UTF-8", "RSA2");
        spiResult.put("response", response);
        spiResult.put("sign", sign);
        return spiResult.toJSONString();
    }

    /**
     * 订单退款前商户回复确认退款结果，result默认设置为WAIT_CONFIRM
     */
    @ResponseBody
    @PostMapping(value = "/refundconfirm")
    public String refundconfirm(@RequestParam Map<String, String> params) throws AlipayApiException {
        logger.info("收到支付宝 spi 接口调用, spi 接口: " + params.get("method") + ", 参数:" + JSON.toJSONString(params));

        JSONObject response = new JSONObject();
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8", "RSA2");

        //验签成功
        if (signVerified) {
            logger.info("order_id：" + params.get("order_id"));
            logger.info("refund_type：" + params.get("refund_type"));

            // 业务参数
//            response.put("result", "ACCEPT");
            // 需调用alipay.marketing.activity.order.refundconfirmcommit接口确认
            response.put("result", "WAIT_CONFIRM");

            //spi 固定响应参数
            response.put("code", 10000);
            response.put("msg", "Success");
            logger.info("spi response：" + JSON.toJSONString(response));
        } else {
            // 验签失败：构造错误码
            response.put("code", 40004);
            response.put("msg", "Business Failed");
            response.put("sub_code", "ISV-VERIFICATION-FAILED");
            response.put("sub_msg", "验签失败");
            logger.error("验签失败");
        }
        String contentToSign = response.toJSONString();
        JSONObject spiResult = new JSONObject();
        String sign = AlipaySignature.rsaSign(contentToSign, privateKey, "UTF-8", "RSA2");
        spiResult.put("response", response);
        spiResult.put("sign", sign);
        return spiResult.toJSONString();
    }

    /**
     * 随机生成12位的券码，前三位大写字母，后九位数字
     */
    private String codeGenerator() {
        // 生成随机字符串的前3位
        String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        Random random = new Random();
        StringBuilder result = new StringBuilder(3);
        for (int i = 0; i < 3; i++) {
            result.append(letters.charAt(random.nextInt(letters.length())));
        }

        // 生成随机数字的后9位
        for (int i = 0; i < 9; i++) {
            result.append(random.nextInt(10)); // 生成0-9之间的数字
        }

        return result.toString();
    }
}
